﻿/* Filename: InitiativeList.as 
 *
 * Description: This class 
 *
 * Anthony Scott and Tyler Samson
 * Feb 2008
 * @ Sierra Nevada College
 */
 class InitiativeList {
	
	private var _hash:Array;
	private var _currentNode:Node;
	private var _isEnd:Boolean;
	private var _topNode:Node;
	
	public function InitiativeList(p_objects:Array, p_initiative:Number) {
		_hash = new Array(p_initiative);
		addArrayToHash(p_objects, p_initiative);
		
		/*for(var i = 0; i < p_objects.length; i++) {
			_hash[i] = new Node(null, null);
		}*/
		
	}
	
	public function addToHash(p_object:Object, p_initiative:Number):Void {
		var _initiative:Number = Math.round(Math.random()*p_initiative);
		_isEnd = false;
		
		if(!_hash[_initiative]) {
			_hash[_initiative] = new Node(p_object, _initiative);
			
			if(!_currentNode) {
				_currentNode = _hash[_initiative];
				_isEnd = true;
				_topNode = _hash[_initiative];
			}else if(_currentNode.getIndex() < _hash[_initiative].getIndex()) {
				_currentNode = _hash[_initiative];
				_topNode = _hash[_initiative];
			}
		} else {
			var _next:Node = _hash[_initiative];
			while (_next.getNext()) {
				_next = _next.getNext();
			}
			_next.setNext(new Node(p_object, _initiative));
			
			if(_currentNode.getIndex() < _next.getIndex()) {
				_currentNode = _next;
			}
		}
	}
	
	public function addArrayToHash(p_array:Array, p_initiative:Number):Void {
		for(var i = 0; i < p_array.length; i++) {
			addToHash(p_array[i], p_initiative);
		}
	}
	
	public function getCurrentNode():Demon {
		var _returnObject:Object = _currentNode;
		_currentNode = findNextNode();
		trace("Initiative = " + _returnObject.getIndex() + " Creature: " + _returnObject.getObject().getName());
		//trace("Current Node = " + _currentNode.getObject().getName() + "Top Node: " + _topNode.getObject().getName());
		return _returnObject.getObject();
	}
	
	public function isEnd():Boolean {
		return _isEnd;
	}
	
	public function findNextNode():Node {
		var _returnNode:Node = null;
		
		if (!_currentNode.getNext()) {
			var _index:Number = _currentNode.getIndex() - 1;
			while (_index >= 0 && !_returnNode) {
				if (_hash[_index]) {
					_isEnd = false;
					_returnNode = _hash[_index];
				}
				_index--;
			}
			if (!_returnNode) {
				_isEnd = true;
				_returnNode = _topNode;
			}
		} else {
			_isEnd = false;
			_returnNode = _currentNode.getNext();
		}
		
		return _returnNode;
	}
	
	public function removeObject(p_object:Object):Void {
		var _id:Number = p_object.getUniqueId();
		var _found:Boolean = false;
		var _node:Node = findNode(p_object);
		
		trace("Object: " + _node.getObject().getName() + "\nid: " + _node.getObject().getUniqueId() +
				"\nInit: " + _node.getIndex());

		var _fNode = findFollowingNode(_node);
		
		trace("Next: " + _fNode.getObject().getName() + "\nid: " + _fNode.getObject().getUniqueId() +
				"\nInit: " + _fNode.getIndex());
		
		var _pNode = findPrecedingNode(_node);
		
		trace("Previous: " + _pNode.getObject().getName() + "\nid: " + _pNode.getObject().getUniqueId() +
				"\nInit: " + _pNode.getIndex());
		
		if (_fNode.getIndex() == _node.getIndex()) {
			_hash[_fNode.getIndex()] = _fNode;
		} else {
			_hash[_node.getIndex()] = null;
		}
		
		if (_pNode.getIndex() == _node.getIndex()) {
			if (_pNode.getIndex() == _fNode.getIndex()) {
				_pNode.setNext(_fNode);
			} else {
				_pNode.setNext(null);
			}
		}
		
		if (_node.compareTo(_currentNode)) {
			_currentNode = findNextNode();
			_topNode = _currentNode;
		}
		
		delete _node;
	}
	
	public function findNode(p_object:Object):Node {
		var _id:Number = p_object.getUniqueId();
		var _found:Boolean = false;
		var _returnObject:Node;
		
		for (var i = 0; i < _hash.length; i++) {
			if (!_found) {
				var _nextNode:Node = _hash[i];
				
				if (_id == _nextNode.getObject().getUniqueId()) {
					_returnObject = _nextNode;
					_found = true;
				}
			}
			
			if (!_found) {
				while (_nextNode.getNext()) {
					_nextNode = _nextNode.getNext();
					
					if (_id == _nextNode.getObject().getUniqueId()) {
						_returnObject = _nextNode;
						_found = true;
					}
				}
			}
		}
		
		return _returnObject;
	}
	
	private function findFollowingNode(p_node:Node):Node {
		var _followingNode:Node = null;
		
		if (p_node.getNext()) {
			_followingNode = p_node.getNext();
		}
		
		var _index = p_node.getIndex();
		while (_followingNode == null) {
			if (_index + 1 < _hash.length) {
				_index = _index + 1;
			} else {
				_index = 0;
			}
			
			if (_hash[_index]) {
				_followingNode = _hash[_index];
			}
		}
		
		return _followingNode;
	}
	
	private function findPrecedingNode(p_node:Node):Node {
		var _precedingNode:Node = null;
		
		if (!_hash[p_node.getIndex()].compareTo(p_node)) {
			var _nextNode = _hash[p_node.getIndex()];
			
			while (!_nextNode.getNext().compareTo(p_node)) {
				_nextNode = _nextNode.getNext();
			}
			
			_precedingNode = _nextNode;
		} else {

			var _index = p_node.getIndex();
			while (_precedingNode == null) {
				if (_index - 1 >= 0) {
					_index = _index - 1;
				} else {
					_index = _hash.length - 1;
				}
			
				if (_hash[_index]) {
					var _nextNode:Node = _hash[_index];
					
					while (_nextNode.getNext()) {
						_nextNode = _nextNode.getNext();
					}
					
					_precedingNode = _nextNode;
				}
			}
		}
		
		return _precedingNode;
	}
	
	public function listToString():String {
		var _string:String = "";
		
		for (var i = 0; i < _hash.length; i++) {
			var _nextNode:Node = _hash[i];
			
			if (_nextNode) {
				_string = _string.concat("\n", _nextNode.getIndex(), "\t-\t", _nextNode.getObject().getName(), "\t", _nextNode.getObject().getOwner().getName());
				
				while (_nextNode.getNext()) {
					_nextNode = _nextNode.getNext();
					_string = _string.concat("\n", _nextNode.getIndex(), "\t-\t",  _nextNode.getObject().getName(), "\t", _nextNode.getObject().getOwner().getName());
				}
			}
			
		}
		
		return _string;
	}
}